from PyQt5.QtWidgets import QWidget, QGraphicsView, QGraphicsScene, QGraphicsLineItem, QVBoxLayout, QStatusBar, QSizePolicy, QGraphicsPixmapItem
from PyQt5.QtCore import Qt, QPointF, pyqtSignal, QRectF
from PyQt5.QtGui import QPainter, QPen, QPolygonF, QTransform, QPixmap

import threading

from trace_visualizer_py.common import *


# 地图场景类
class MapScene(QGraphicsScene):
    sig_ship_move = pyqtSignal(QPointF)  # 定义信号，用于发送鼠标位置
    def __init__(self, scale=10, offx=0, offy=0):
        super().__init__()
        
        self.ship_points = []
        self.ship_lines = []  # 存储船行过的轨迹线段
        self.ship_x = common_data['cfg_basic'].get('shipX')
        self.ship_y = common_data['cfg_basic'].get('shipY')
        self.ship_state = common_data['cfg_basic'].get('shipState')
        self.ship_img_item = None

        self.mouse_points = []  # 仅存储鼠标绘制的点（目标点）
        self.mouse_lines = []  # 存储鼠标绘制的线段

        self.lock = threading.Lock()
        self.scale_factor = scale  # 缩放比(像素距离/实际距离)
        self.offset = QPointF(offx, offy)  # 偏移

        self.last_point_item = None  # 存储最后一个点的图形项

        self.x_axis = None
        self.y_axis = None
        self.pool_area = QRectF(0, 0, 0, 0)  # 初始化水池区，默认长宽为 0
        self.pool_width = 0
        self.pool_length = 0
        self.grid_lines = []  # 存储网格线
        self.grid_labels = []  # 存储网格坐标数字

        self.uwb_img_path = '/home/ajream/quickDir/rosStudy/ros2qtws/src/trace_visualizer_py/resource/imgs/station48.png'
        self.ship_img_path = '/home/ajream/quickDir/rosStudy/ros2qtws/src/trace_visualizer_py/resource/imgs/ship48.png'
        self.start_img_path = '/home/ajream/quickDir/rosStudy/ros2qtws/src/trace_visualizer_py/resource/imgs/start48.png'
        self.end_img_path = '/home/ajream/quickDir/rosStudy/ros2qtws/src/trace_visualizer_py/resource/imgs/end48.png'
        self.uwb0_point = QPointF(0,0)
        self.uwb1_point = QPointF(0,0)
        self.uwb2_point = QPointF(0,0)

        # 初始化坐标轴
        self.draw_axes()
        # self.set_pool_area()
        # self.draw_pool_area()
        
        # self.addLine(10, 10, 50, 50, QPen(Qt.red, 2))

    def set_pool_area(self, length, width):
        """设置矩形绘图区的长宽"""
        self.pool_width = width
        self.pool_length = length
        self.pool_area = QRectF(self.offset.x(), self.offset.y(), length*self.scale_factor, width*self.scale_factor)
        # self.draw_pool_area()  # 重新绘制矩形绘图区
        # self.draw_ship(0, 0, 90)

    def set_uwb_pos(self, x0, y0, x1, y1, x2, y2):
        self.uwb0_point.setX(x0)
        self.uwb0_point.setY(y0)
        self.uwb1_point.setX(x1)
        self.uwb1_point.setY(y1)
        self.uwb2_point.setX(x2)
        self.uwb2_point.setY(y2)

    def get_mouse_points(self):
        """获取目标轨迹点"""
        with self.lock:
            return self.mouse_points.copy()
        
    
    def add_point(self, x, y, is_mouse=False):
        '''
        往画布添加点：
        x, y: 实际地图坐标（单位m）
        '''
        with self.lock:
            new_point = QPointF(x, y)
            
            sx, sy = self.__convert_point_to_scene(x, y)
            scene_point = QPointF(sx, sy)
            # 检查点是否在矩形绘图区内
            if not self.pool_area.contains(scene_point):
                # print(f'{sx},{sy}不在矩形区')
                return

            if is_mouse:
                self.mouse_points.append(new_point)
                self.sig_ship_move.emit(new_point)
                self.draw_points(self.mouse_points, is_mouse, QPen(Qt.darkMagenta, 2))
            else:
                self.sig_ship_move.emit(new_point)  #发射信号给状态栏修改船目前位置
                self.ship_points.append(new_point)
                self.draw_points(self.ship_points, is_mouse)

    def update_axes(self, view):
        # 根据视图的范围更新坐标轴长度
        view_rect = view.viewport().rect()
        scene_rect = view.mapToScene(view_rect).boundingRect()
        self.draw_axes()
    
    def clear_content(self):
        """清空场景内容，但保留坐标轴、矩形边框、网格线、坐标数字"""
        with self.lock:
            # # 移除所有线段
            # for line in self.lines:
            #     self.removeItem(line)
            # self.lines.clear()
            # # 移除最后一个点
            # if self.last_point_item:
            #     self.removeItem(self.last_point_item)
            #     self.last_point_item = None
            # 清空点列表
            
            self.ship_points.clear()
            self.mouse_points.clear()
            self.ship_lines.clear()
            self.mouse_lines.clear()
            self.ship_img_item = None
            self.last_point_item = None
            self.clear()
            self.draw_axes()
            self.draw_pool_area()
            self.draw_uwbs(self.uwb0_point, self.uwb1_point, self.uwb2_point)
            self.draw_ship(0, 0, 0)
    
    def draw_axes(self, pen=QPen(Qt.lightGray, 1)):
        pen.setCosmetic(True)  # 设置为像素级固定宽度
        # if self.x_axis:
        #     self.removeItem(self.x_axis)
        # if self.y_axis:
        #     self.removeItem(self.y_axis)

        self.x_axis = self.addLine(-100, 0, 100, 0, pen)  # X轴
        self.y_axis = self.addLine(0, -100, 0, 100, pen)  # Y轴

    def draw_pool_area(self):
        """绘制矩形绘图区"""
        # 移除旧的网格线和标签
        # for line in self.grid_lines:
        #     self.removeItem(line)
        # for label in self.grid_labels:
        #     self.removeItem(label)
        self.grid_lines.clear()
        self.grid_labels.clear()

        pen = QPen(Qt.gray, 2)
        pen.setCosmetic(True)  # 设置为像素级固定宽度
        rect_item = self.addRect(self.pool_area, pen)
        self.grid_lines.append(rect_item)

        width = self.pool_area.width()
        height = self.pool_area.height()
        mx_len = int(max(width, height))
        grid_num = 20 if mx_len >= 60*self.scale_factor else (mx_len/self.scale_factor)//5
        #print("grid_num: %d" % grid_num)
        # 绘制网格线
        for i in range(0, mx_len+1, int(mx_len//grid_num)):
            if i % int((mx_len//grid_num) * 4) == 0:
                pen.setWidth(1)  # 粗线
                pen.setColor(Qt.darkCyan)  # 灰色
            else:
                pen.setWidth(1)  # 细线
                pen.setColor(Qt.lightGray)  # 淡灰色
            if i== 0:
                    # 绘制水平线左边的纵坐标数字
                    label = self.addText("0")
                    # 临时反转 Y 轴变换，让数字正常显示
                    label.setTransform(QTransform().scale(1, -1))
                    label.setPos(-20, -2)  # 调整位置
                    
                    self.grid_labels.append(label)
            if i <= width:
                line = self.addLine(i, 0, i, height, pen)
                self.grid_lines.append(line)
                if i!= 0:
                    # 绘制垂直线下方的横坐标数字
                    label = self.addText(f"{i//self.scale_factor}")
                    # 临时反转 Y 轴变换，让数字正常显示
                    label.setTransform(QTransform().scale(1, -1))
                    label.setPos(i-10, -2)
                    self.grid_labels.append(label)
            if i <= height:
                line = self.addLine(0, i, width, i, pen)
                self.grid_lines.append(line)
                if i!= 0:
                    # 绘制水平线左边的纵坐标数字
                    label = self.addText(f"{i//self.scale_factor}")
                    # 临时反转 Y 轴变换，让数字正常显示
                    label.setTransform(QTransform().scale(1, -1))
                    label.setPos(-25, i+15)  # 调整位置
                    self.grid_labels.append(label)

    def draw_points(self, points, is_mouse=False, pen=QPen(Qt.blue,2)):
        if len(points) > 5000:  # 限制点数
            points.pop(0)
            if is_mouse and self.mouse_lines and len(self.mouse_lines)>0:
                self.removeItem(self.mouse_lines[0])
                self.mouse_lines.pop(0)
            elif not is_mouse:
                if self.ship_lines and len(self.ship_lines)>0:
                    self.removeItem(self.ship_lines[0])
                    self.ship_lines.pop(0)

        if len(points) > 1:
            # 绘制折线
            pen.setCosmetic(True)  # 设置为像素级固定宽度
            # 将实际坐标转换为场景坐标
            scene_x1, scene_y1 = self.__convert_point_to_scene(points[-2].x(), points[-2].y())
            scene_x2, scene_y2 = self.__convert_point_to_scene(points[-1].x(), points[-1].y())

            line = self.addLine(scene_x1, scene_y1, scene_x2, scene_y2, pen)
            if is_mouse:
                self.mouse_lines.append(line)
            else:
                self.ship_lines.append(line)
        if not is_mouse:
            self.draw_ship(points[-1].x(), points[-1].y(), points[-1].x()%360)

        # 绘制最后一个点（红色大点）
        # if self.last_point_item:
        #     self.removeItem(self.last_point_item)
        # scene_x, scene_y = self.__convert_point_to_scene(points[-1].x(), points[-1].y())
        # self.last_point_item = self.addEllipse(scene_x - 2.5, scene_y - 2.5, 5, 5, QPen(Qt.red, 5), Qt.red)
        # self.last_point_item.pen().setCosmetic(True)  # 设置为像素级固定宽度


    def draw_uwb(self, x, y):
        sx, sy = self.__convert_point_to_scene(x, y)
        if not self.pool_area.contains(QPointF(sx, sy)):
            print(f'{sx},{sy}不在矩形区')
            return
        self.__draw_img(self.uwb_img_path, sx, sy, 0)

    def draw_uwbs(self, p1, p2, p3):
        self.draw_uwb(p1.x(), p1.y())
        self.draw_uwb(p2.x(), p2.y())
        self.draw_uwb(p3.x(), p3.y())

    def draw_start(self, x, y):
        sx, sy = self.__convert_point_to_scene(x, y)
        # 检查点是否在矩形绘图区内
        if not self.pool_area.contains(QPointF(sx, sy)):
            print(f'{sx},{sy}不在矩形区')
            return
        self.__draw_img(self.start_img_path, sx, sy, 0)

    def draw_end(self, x, y):
        sx, sy = self.__convert_point_to_scene(x, y)
        if not self.pool_area.contains(QPointF(sx, sy)):
            print(f'{sx},{sy}不在矩形区')
            return
        self.__draw_img(self.end_img_path, sx, sy, 0)
    
    def draw_ship(self, x, y, angle):
        sx, sy = self.__convert_point_to_scene(x, y)
        if not self.pool_area.contains(QPointF(sx, sy)):
            print(f'{sx},{sy}不在矩形区')
            return
        self.__draw_img(self.ship_img_path, sx, sy, angle-90, is_ship=True)

    def __draw_img(self, img_path, scene_x=0, scene_y=0, rotation_angle=0, is_ship=False):
        pixmap = QPixmap(img_path)
        vertical_transform = QTransform().scale(1, -1)
        pixmap = pixmap.transformed(vertical_transform)  #上下翻转
        
        # pixmap = pixmap.transformed(QTransform().rotate(rotation_angle))
        
        x = scene_x - pixmap.width()/2

        if is_ship:
            y = scene_y - pixmap.height()/2
            if not self.ship_img_item:
                image_item = QGraphicsPixmapItem(pixmap)
                image_item.setTransformOriginPoint(pixmap.width() / 2, pixmap.height() / 2)  # 设置旋转中点
                self.ship_img_item = image_item
                self.addItem(image_item)
            else:
                image_item = self.ship_img_item

        else:
            image_item = QGraphicsPixmapItem(pixmap)
            y = scene_y
            self.addItem(image_item)
            
        image_item.setPos(QPointF(x, y))
        image_item.setRotation(rotation_angle)

    def __convert_point_to_scene(self, x, y):
        '''将实际坐标转换为画布场景坐标'''
        scene_x = self.offset.x() + x * self.scale_factor
        scene_y = self.offset.y() + y * self.scale_factor
        return scene_x, scene_y

    def convert_point_to_map(self, x, y):
        '''将画布场景坐标转换为实际坐标'''
        map_x = (x - self.offset.x()) / self.scale_factor
        map_y = (y - self.offset.y()) / self.scale_factor
        return map_x, map_y


common_data['scene_map'] = MapScene()
